// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_CERT_SIGNED_CERTIFICATE_TIMESTAMP_H_
#define NET_CERT_SIGNED_CERTIFICATE_TIMESTAMP_H_

#include <string>
#include <vector>

#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "net/base/hash_value.h"
#include "net/base/net_export.h"

namespace base {
class Pickle;
class PickleIterator;
}

namespace net {

// Structures related to Certificate Transparency (RFC6962).
namespace ct {

    // LogEntry struct in RFC 6962, Section 3.1
    struct NET_EXPORT LogEntry {
        // LogEntryType enum in RFC 6962, Section 3.1
        enum Type {
            LOG_ENTRY_TYPE_X509 = 0,
            LOG_ENTRY_TYPE_PRECERT = 1
        };

        LogEntry();
        ~LogEntry();
        void Reset();

        Type type;

        // Set if type == LOG_ENTRY_TYPE_X509
        std::string leaf_certificate;

        // Set if type == LOG_ENTRY_TYPE_PRECERT
        SHA256HashValue issuer_key_hash;
        std::string tbs_certificate;
    };

    // Helper structure to represent Digitally Signed data, as described in
    // Sections 4.7 and 7.4.1.4.1 of RFC 5246.
    struct NET_EXPORT_PRIVATE DigitallySigned {
        enum HashAlgorithm {
            HASH_ALGO_NONE = 0,
            HASH_ALGO_MD5 = 1,
            HASH_ALGO_SHA1 = 2,
            HASH_ALGO_SHA224 = 3,
            HASH_ALGO_SHA256 = 4,
            HASH_ALGO_SHA384 = 5,
            HASH_ALGO_SHA512 = 6,
        };

        enum SignatureAlgorithm {
            SIG_ALGO_ANONYMOUS = 0,
            SIG_ALGO_RSA = 1,
            SIG_ALGO_DSA = 2,
            SIG_ALGO_ECDSA = 3
        };

        DigitallySigned();
        ~DigitallySigned();

        // Returns true if |other_hash_algorithm| and |other_signature_algorithm|
        // match this DigitallySigned hash and signature algorithms.
        bool SignatureParametersMatch(
            HashAlgorithm other_hash_algorithm,
            SignatureAlgorithm other_signature_algorithm) const;

        HashAlgorithm hash_algorithm;
        SignatureAlgorithm signature_algorithm;
        // 'signature' field.
        std::string signature_data;
    };

    // SignedCertificateTimestamp struct in RFC 6962, Section 3.2.
    struct NET_EXPORT SignedCertificateTimestamp
        : public base::RefCountedThreadSafe<SignedCertificateTimestamp> {
        // Predicate functor used in maps when SignedCertificateTimestamp is used as
        // the key.
        struct NET_EXPORT LessThan {
            bool operator()(const scoped_refptr<SignedCertificateTimestamp>& lhs,
                const scoped_refptr<SignedCertificateTimestamp>& rhs) const;
        };

        // Version enum in RFC 6962, Section 3.2.
        enum Version {
            V1 = 0,
        };

        // Source of the SCT - supplementary, not defined in CT RFC.
        // Note: The numeric values are used within histograms and should not change
        // or be re-assigned.
        enum Origin {
            SCT_EMBEDDED = 0,
            SCT_FROM_TLS_EXTENSION = 1,
            SCT_FROM_OCSP_RESPONSE = 2,
            SCT_ORIGIN_MAX,
        };

        SignedCertificateTimestamp();

        void Persist(base::Pickle* pickle);
        static scoped_refptr<SignedCertificateTimestamp> CreateFromPickle(
            base::PickleIterator* iter);

        Version version;
        std::string log_id;
        base::Time timestamp;
        std::string extensions;
        DigitallySigned signature;
        Origin origin;
        // The log description is not one of the SCT fields, but a user-readable
        // name defined alongside the log key. It should not participate
        // in equality checks as the log's description could change while
        // the SCT would be the same.
        std::string log_description;

    private:
        friend class base::RefCountedThreadSafe<SignedCertificateTimestamp>;

        ~SignedCertificateTimestamp();

        DISALLOW_COPY_AND_ASSIGN(SignedCertificateTimestamp);
    };

} // namespace ct

} // namespace net

#endif // NET_CERT_SIGNED_CERTIFICATE_TIMESTAMP_H_
